/**********************************************************************************************************************
 *
 * Project:    mGameEngine
 * File:       revolutejoint.cpp
 * Author:     karooolek
 * Created on: Nov 19, 2009
 *
 **********************************************************************************************************************/

#include "revolutejoint.h"

namespace mGameEngine
{

namespace Physics
{

RevoluteJoint::RevoluteJoint(const Vector3 &point1, const Vector3 &point2, const Vector3 &axis1, const Vector3 &axis2,
                             float maxTwist) :
    Joint(),
    _maxTwist(maxTwist)
{
    _anchor1 = Matrix4x4(Quaternion(axis1), point1);
    _anchor2 = Matrix4x4(Quaternion(axis2), point2);
}

RevoluteJoint::~RevoluteJoint()
{
    // everything done in ~Joint()
}

void RevoluteJoint::setMaximalTwist(float maxTwist)
{
    // maximal twist less than 180 degrees
    if(maxTwist < 0.0f || maxTwist > M_PI)
    {
        return;
    }

    _maxTwist = maxTwist;

    if(_joint)
    {
        // TODO
    }
}

void RevoluteJoint::create(NxActor *actor1, NxActor *actor2) const
{
    // two actors required
    if(!actor1 || !actor2)
    {
        return;
    }

    // already created
    if(_created)
    {
        return;
    }

    // create joint
    NxRevoluteJointDesc desc;

    // assign first actor
    if(actor1->isDynamic())
    {
        desc.actor[0] = actor1;
        desc.localNormal[0] = NxVec3(_anchor1.m[2]);
        desc.localAxis[0] = NxVec3(_anchor1.m[0]);
        desc.localAnchor[0] = NxVec3(_anchor1.m[3]);
    }
    else
    {
        desc.actor[0] = NULL;
        desc.localNormal[0] = actor1->getGlobalOrientation() * NxVec3(_anchor1.m[2]);
        desc.localAxis[0] = actor1->getGlobalOrientation() * NxVec3(_anchor1.m[0]);
        desc.localAnchor[0] = actor1->getGlobalPose() * NxVec3(_anchor1.m[3]);
    }

    // assign second actor
    if(actor2->isDynamic())
    {
        desc.actor[1] = actor2;
        desc.localNormal[1] = -NxVec3(_anchor2.m[2]);
        desc.localAxis[1] = -NxVec3(_anchor2.m[0]);
        desc.localAnchor[1] = NxVec3(_anchor2.m[3]);
    }
    else
    {
        desc.actor[1] = NULL;
        desc.localNormal[1] = actor2->getGlobalOrientation() * -NxVec3(_anchor2.m[2]);
        desc.localAxis[1] = actor2->getGlobalOrientation() * -NxVec3(_anchor2.m[0]);
        desc.localAnchor[1] = actor2->getGlobalPose() * NxVec3(_anchor2.m[3]);
    }

    if(_maxTwist < M_PI)
    {
        desc.flags |= NX_SJF_TWIST_LIMIT_ENABLED;
        desc.limit.low.value = -_maxTwist;
        desc.limit.high.value = _maxTwist;
    }

    _joint = actor1->getScene().createJoint(desc);

    // problems while creating joint
    if(_joint == NULL)
    {
        return;
    }

    // joint is created
    _created = true;
}


}
}

